{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Otto商品分类——KMeans聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#导入必要的工具包\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "from sklearn.preprocessing import normalize\n",
    "from sklearn.cluster import MiniBatchKMeans\n",
    "\n",
    "from sklearn import metrics"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 读取数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>feat_1</th>\n",
       "      <th>feat_2</th>\n",
       "      <th>feat_3</th>\n",
       "      <th>feat_4</th>\n",
       "      <th>feat_5</th>\n",
       "      <th>feat_6</th>\n",
       "      <th>feat_7</th>\n",
       "      <th>feat_8</th>\n",
       "      <th>feat_9</th>\n",
       "      <th>...</th>\n",
       "      <th>feat_85</th>\n",
       "      <th>feat_86</th>\n",
       "      <th>feat_87</th>\n",
       "      <th>feat_88</th>\n",
       "      <th>feat_89</th>\n",
       "      <th>feat_90</th>\n",
       "      <th>feat_91</th>\n",
       "      <th>feat_92</th>\n",
       "      <th>feat_93</th>\n",
       "      <th>target</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>Class_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>Class_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>Class_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>Class_1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>Class_1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 95 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "   id  feat_1  feat_2  feat_3  feat_4  feat_5  feat_6  feat_7  feat_8  feat_9  \\\n",
       "0   1       1       0       0       0       0       0       0       0       0   \n",
       "1   2       0       0       0       0       0       0       0       1       0   \n",
       "2   3       0       0       0       0       0       0       0       1       0   \n",
       "3   4       1       0       0       1       6       1       5       0       0   \n",
       "4   5       0       0       0       0       0       0       0       0       0   \n",
       "\n",
       "    ...     feat_85  feat_86  feat_87  feat_88  feat_89  feat_90  feat_91  \\\n",
       "0   ...           1        0        0        0        0        0        0   \n",
       "1   ...           0        0        0        0        0        0        0   \n",
       "2   ...           0        0        0        0        0        0        0   \n",
       "3   ...           0        1        2        0        0        0        0   \n",
       "4   ...           1        0        0        0        0        1        0   \n",
       "\n",
       "   feat_92  feat_93   target  \n",
       "0        0        0  Class_1  \n",
       "1        0        0  Class_1  \n",
       "2        0        0  Class_1  \n",
       "3        0        0  Class_1  \n",
       "4        0        0  Class_1  \n",
       "\n",
       "[5 rows x 95 columns]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取训练数据\n",
    "dpath = './data/'\n",
    "train = pd.read_csv(dpath +\"Otto_train.csv\")\n",
    "train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.06388766,  0.        ,  0.        , ...,  0.        ,\n",
       "         0.        ,  0.        ],\n",
       "       [ 0.        ,  0.        ,  0.        , ...,  0.        ,\n",
       "         0.        ,  0.        ],\n",
       "       [ 0.        ,  0.        ,  0.        , ...,  0.        ,\n",
       "         0.        ,  0.        ],\n",
       "       ..., \n",
       "       [ 0.        ,  0.        ,  0.        , ...,  0.        ,\n",
       "         0.        ,  0.        ],\n",
       "       [ 0.06835859,  0.        ,  0.        , ...,  0.20507578,\n",
       "         0.68358593,  0.        ],\n",
       "       [ 0.        ,  0.        ,  0.        , ...,  0.        ,\n",
       "         0.11585689,  0.        ]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train = train['target']   \n",
    "X_train = train.drop([\"id\", \"target\"], axis=1)\n",
    "\n",
    "\n",
    "#用于每个样本的聚类结果\n",
    "train_id = train['id']\n",
    "\n",
    "#数据进行归一：每个样本的模长为1\n",
    "normalize(X_train, norm=\"l2\", copy=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## KMeans聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 一个参数点（聚类数据为K）的模型\n",
    "def K_cluster_analysis(K, X):\n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    \n",
    "    #K-means,在训练集上训练\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    y_pred = mb_kmeans.fit_predict(X)\n",
    "    \n",
    "    # K值的评估标准\n",
    "    #本案例中训练数据有标签，可采用有参考模型的评价指标\n",
    "    #v_score = metrics.v_measure_score(y_val, y_val_pred)\n",
    "    \n",
    "    #亦可采用无参考默的评价指标：轮廓系数Silhouette Coefficient和Calinski-Harabasz Index\n",
    "    #这两个分数值越大则聚类效果越好\n",
    "    CH_score = metrics.calinski_harabaz_score(X, y_pred)\n",
    "    \n",
    "    #轮廓系数Silhouette Coefficient在大样本时计算太慢\n",
    "    #si_score = metrics.silhouette_score(X, y_pred)\n",
    "    \n",
    "    print(\"CH_score: {}\".format(CH_score))\n",
    "    #print(\"si_score: {}\".format(si_score))\n",
    "    \n",
    "    return CH_score#,si_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 10\n",
      "CH_score: 3395.1381464\n",
      "K-means begin with clusters: 20\n",
      "CH_score: 2076.36444475\n",
      "K-means begin with clusters: 30\n",
      "CH_score: 1835.32982592\n",
      "K-means begin with clusters: 40\n",
      "CH_score: 1937.01645964\n",
      "K-means begin with clusters: 50\n",
      "CH_score: 1585.20412251\n",
      "K-means begin with clusters: 60\n",
      "CH_score: 1358.48651964\n"
     ]
    }
   ],
   "source": [
    "# 设置超参数（聚类数目K）搜索范围\n",
    "Ks = [10, 20, 30,40,50,60]\n",
    "CH_scores = []\n",
    "#si_scores = []\n",
    "for K in Ks:\n",
    "    ch = K_cluster_analysis(K, X_train)\n",
    "    CH_scores.append(ch)\n",
    "    #si_scores.append(si)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a0e632650>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制不同K对应的聚类的性能，找到最佳模型／参数（分数最高）\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.plot(Ks, np.array(CH_scores), 'b-',label = 'CH_scores')\n",
    "\n",
    "\n",
    "### 最佳超参数\n",
    "index = np.unravel_index(np.argmax(CH_scores, axis=None), len(CH_scores))\n",
    "Best_K = Ks[ index[0]]\n",
    "\n",
    "print(Best_K)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 用最佳的K再次聚类，得到聚类结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "mb_kmeans = MiniBatchKMeans(n_clusters = Best_K)\n",
    "\n",
    "y_pred = mb_kmeans.fit_predict(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([4, 4, 4, ..., 5, 4, 4], dtype=int32)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#保存聚类结果\n",
    "feat_names_Kmeans = \"Kmeans_\" + str(Best_K)\n",
    "\n",
    "y = pd.Series(data = y_train, name = 'target')\n",
    "train_kmeans = pd.concat([train_id, pd.Series(name = feat_names_Kmeans, data = y_pred), y], axis = 1)\n",
    "train_kmeans.to_csv(dpath +'Otto_FE_train_KMeans.csv',index=False,header=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 保存KMeans模型，用于后续对测试数据的聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import cPickle\n",
    "\n",
    "cPickle.dump(mb_kmeans, open(\"mb_kmeans.pkl\", 'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
